Add ot_lgetxattrat and ot_lsetxattrat utils
authorAlexander Larsson <alexl@redhat.com>
Wed, 3 Dec 2014 09:58:41 +0000 (10:58 +0100)
committerAlexander Larsson <alexl@redhat.com>
Mon, 8 Dec 2014 09:39:39 +0000 (10:39 +0100)
These are implementation of the missing corresponding syscalls that
are done with the /proc/self/fd mechanism described at:

https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html

https://bugzilla.gnome.org/show_bug.cgi?id=741125

src/libotutil/ot-fs-utils.c
src/libotutil/ot-fs-utils.h

index 1d02003e65568b96d68265c9c864d046aa6b763a..966f31ae007347bca0bf8b3c131fc36a15ac8c8a 100644 (file)
@@ -21,6 +21,8 @@
 #include "config.h"
 
 #include "ot-fs-utils.h"
+#include "libgsystem.h"
+#include <attr/xattr.h>
 
 int
 ot_opendirat (int dfd, const char *path, gboolean follow)
@@ -48,3 +50,68 @@ ot_gopendirat (int             dfd,
   return TRUE;
 }
 
+GBytes *
+ot_lgetxattrat (int            dfd,
+                const char    *path,
+                const char    *attribute,
+                GError       **error)
+{
+  /* A workaround for the lack of lgetxattrat(), thanks to Florian Weimer:
+   * https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html
+   */
+  gs_free char *full_path = g_strdup_printf ("/proc/self/fd/%d/%s", dfd, path);
+  GBytes *bytes = NULL;
+  ssize_t bytes_read, real_size;
+  char *buf;
+
+  do
+    bytes_read = lgetxattr (full_path, attribute, NULL, 0);
+  while (G_UNLIKELY (bytes_read < 0 && errno == EINTR));
+  if (G_UNLIKELY (bytes_read < 0))
+    {
+      ot_util_set_error_from_errno (error, errno);
+      goto out;
+    }
+
+  buf = g_malloc (bytes_read);
+  do
+    real_size = lgetxattr (full_path, attribute, buf, bytes_read);
+  while (G_UNLIKELY (real_size < 0 && errno == EINTR));
+  if (G_UNLIKELY (real_size < 0))
+    {
+      ot_util_set_error_from_errno (error, errno);
+      g_free (buf);
+      goto out;
+    }
+
+  bytes = g_bytes_new_take (buf, real_size);
+ out:
+  return bytes;
+}
+
+gboolean
+ot_lsetxattrat (int            dfd,
+                const char    *path,
+                const char    *attribute,
+                const void    *value,
+                gsize          value_size,
+                int            flags,
+                GError       **error)
+{
+  /* A workaround for the lack of lsetxattrat(), thanks to Florian Weimer:
+   * https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html
+   */
+  gs_free char *full_path = g_strdup_printf ("/proc/self/fd/%d/%s", dfd, path);
+  int res;
+
+  do
+    res = lsetxattr (full_path, "user.ostreemeta", value, value_size, flags);
+  while (G_UNLIKELY (res == -1 && errno == EINTR));
+  if (G_UNLIKELY (res == -1))
+    {
+      ot_util_set_error_from_errno (error, errno);
+      return FALSE;
+    }
+
+  return TRUE;
+}
index d7ece4fa6bb6c3982a84e2edfa4b4cabcda7404b..6d4a37248ebb387081ee63312af00acca97db247 100644 (file)
@@ -31,5 +31,18 @@ gboolean ot_gopendirat (int             dfd,
                         int            *out_fd,
                         GError        **error);
 
+GBytes * ot_lgetxattrat (int            dfd,
+                         const char    *path,
+                         const char    *attribute,
+                         GError       **error);
+
+gboolean ot_lsetxattrat (int            dfd,
+                         const char    *path,
+                         const char    *attribute,
+                         const void    *value,
+                         gsize          value_size,
+                         int            flags,
+                         GError       **error);
+
 G_END_DECLS